TSKaigi Kansai 2024 -「as(型アサーション)を書く前にできること」というテーマで登壇しました #TSKaigiKansai
先日、「TSKaigi Kansai 2024」というイベントにて、「as(型アサーション)を書く前にできること」というテーマで登壇しました。
登壇資料
登壇資料はこちらです。
TSのコードレビューをしていて感じること
私は普段TSのコードレビューをする機会が多いです。
その中でany
を使うことは良くないという認識が広がりつつある一方、as
に関してはany
ほど広まっておらず、カジュアルに使われることも多いように感じています。
なぜasの濫用は良くないのか
一言で言ってしまえば「コンパイラの挙動を上書きしてしまう」、これに尽きるかと思います。そういう意味では潜在的にany
と同様の副作用があると言えると思います。
よくある意見として、実装者がコンパイラよりもその型についてよく知っている場合はas
を用いても良いというものがあります。
これはたしかにその通りではあるものの、チーム開発においては「(自分はそうかもしれないが)チームの他のメンバーはそうではないかもしれない」ということがあると思うので、やはり避けられるなら避けるに越したことはないと個人的には考えています。
とはいえ全く使わないというのは難しいので用法用量を守るようにしましょう。というのが今回伝えたい趣旨でした。
こんなコード書いてませんか?
簡単なサンプルコードを紹介しました。時間の都合上細かな解説はスキップしましたが、いずれの例も__サブタイプ関係にあるスーパータイプをサブタイプで型アサーションしている__のがよろしくありません。
これは余談で伝わる人に伝われば良いと思っていますが、なんとなく左の例のextendsを使った例については古き良きオブジェクト指向的なニュアンスが分かる人にはすんなり受け入れられる例を用意したつもりです。
一方で右の例関してはユニオン型の例となっており、このパターンになった途端このサブタイプ関係というのを意識しなくなる方が一定いるような気がしています。他の言語ではあまり見ないパターンだからなのかもしれません。
基本的にはこういったパターンについてはガードしておくのが良いです。
ガードのやり方は色々なやり方がありますが、今回はタグ付きユニオンと呼ばれる手法やzodを使ってパース(厳密にはガードではない)する方法を紹介しました。
インターフェース境界でのasには要注意
ここではクライアントからサーバーサイドにPOST APIを叩くようなサンプルコードを例として挙げてみました。
このようにas
を使ってしまうと、型に変化があった際にエラーで落とせない(=インターフェースの変更に気づくことができない)ので特に良くない使い方となっています。
なので明示的に型制約をつけるか、satisfies
をつけることで型を満たしていることをチェックするようにするのが良いです。
本題から外れるので解説はスキップしましたが、通常の型制約の場合はdata.role
はAdmin | User
型と推論されますが、satisfies
とすることでdata.role
はAdmin
と推論されます。
推論結果を保持したまま後続に繋げたいかどうかで適宜使い分けるのが良さそうです。
asが必要な例
最後にas
が必要になるパターンを紹介しました。
ミュータブルなオブジェクトを扱うパターンはas
が必要になる典型的なものかと思います。
こういった場合は関数に切り出すなりしてas
が有効になるスコープが最小限になるようにした上で使うことが望ましいです。
(コメントで補足しておくとさらにGood)
asを書く前に
まとめです。
as
と書く前に「なぜそのas
は必要なのか」を一考してみて欲しいです。
もちろん絶対に自分しか見ないコードやPOCレベルのもの・・・etcなどに於いてはこの限りではないかもしれませんが、少なくともチーム開発において中長期にメンテしていくようなコードにおいてはas
に関する運用を見つめ直すことで読み手側の負荷は下がっていくかもしれません。
所感
私からすると全体的に非常に勉強になる発表が多く、今後の開発に活かせそうなものもたくさんありました。
登壇が決まったときは「こんな発表でいいんだろうか?」とやや不安でしたが、周囲やX等での反響を見てみるとハマる人にはハマる発表だったのかもと感じ、発表して良かったと思えました。
懇親会でもいろいろな方と交流ができてとても楽しいカンファレンスでした。
関西在住なので次回(TSKaigi 2025)参加できるかは微妙なところなのですが、機会があったらぜひまた参加したいです。
発表を聴いてくださった皆様、このような機会をくださった運営の皆様、本当にありがとうございました。